package com.tanhua.sso.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tanhua.sso.mapper.UserMapper;
import com.tanhua.sso.pojo.User;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: cloudy
 * @Description:
 * @Date: Created in 9:48 2021/1/2
 * @ModifiedBy:
 */
@Service
@Slf4j
public class UserService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private  HuanXinService huanXinService;

    public Map login(String phone, String code) {
        String value = redisTemplate.opsForValue().get(SmsService.CHECK_CODE + phone);

        boolean isNew = false;//标记位  默认不是新用户

        //判断验证码是否过期
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        //判断输入的验证码是否正确
        if (!StringUtils.equals(code, value)) {
            return null;
        }

        //验证正确,删除redis中的验证码
        redisTemplate.delete(SmsService.CHECK_CODE + phone);

        //判断是否是新用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getMobile, phone);

        User user = userMapper.selectOne(queryWrapper);

        //this.huanXinService.register(user.getId());
        if (null == user) {//等于null,则mysql中没有该用户
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));



            userMapper.insert(user);
            isNew = true;

            //注册环信用户
            this.huanXinService.register(user.getId());
        }
        //生成token
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", user.getId());

        //生成token
        String token = Jwts.builder()
                .setClaims(claims)//payload，存放数据的位置，不能放置敏感数据，如：密码等
                .signWith(SignatureAlgorithm.HS256, secret)//设置加密方法和加密盐
                .setExpiration(new DateTime().plusHours(12).toDate())//设置过期时间，12小时后过期
                .compact();

        try {
            //发送用户登录成功的消息
            Map<String, Object> msg = new HashMap<>();
            msg.put("id", user.getId());
            msg.put("date", System.currentTimeMillis());

            rocketMQTemplate.convertAndSend("tanhua-sso-login", msg);
        } catch (MessagingException e) {
            log.error("发送消息到mq失败", e);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("isNew", isNew);
        return map;
    }

    public User queryUserByToken(String token) {
        User user = null;
        try {
            // 通过token解析数据
            Map<String, Object> body = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            Long id = Long.valueOf(body.get("id").toString());
            user = new User();
            user.setId(id);

            //先从redis中查询有没有对应用户的手机号
            String redisKey = "TANHUA_USER_MOBILE_" + user.getId();
            if (redisTemplate.hasKey(redisKey)) {
                user.setMobile(redisTemplate.opsForValue().get(redisKey));//将redis中存储的手机号赋给用户
            } else {
                //redis中未查到对应的key,则从mysql中查询手机号并写入user中
                User u = userMapper.selectById(user.getId());
                user.setMobile(u.getMobile());
                //查询到之后,将手机号也写入到redis中,并与token过期时间保持一致
                Long exp = Long.valueOf(body.get("exp").toString()) * 1000;
                redisTemplate.opsForValue().set(redisKey, user.getMobile(), Duration.ofMillis(exp - System.currentTimeMillis()));
            }
        } catch (ExpiredJwtException e) {
            System.out.println("token已经过期！");
        } catch (Exception e) {
            System.out.println("token不合法！");
        }
        return user;
    }
}
